#!/usr/bin/env python
# tvm.py

__version__ = "$Revision: 1.6 $"
__author__  = 'Ramesh Balasubramanian <ramesh@finpy.org>'

import math
import sys

def effrr(rate, numPeriods = 0):
	"""
	-------------------------------------------------------------------------------
	Usage
		return = effrr(rate, numPeriods)
		continuousCompoundedReturn = effrr(rate)
		
	Notes
		effrr - Effective rate of return
		
		rate - Annual percentage rate. Enter as a decimal fraction.
		numPeriods - Number of compounding periods per year, an integer.
		
		return = effrr(rate, numPeriods)  calculates the annual effective rate 
		of return. 
		
		return = effrr(rate) returns the continuous compounding rate (e^Rate-1)
		
	Examples
		In [1]: import finpy	

		In [2]: finpy.effrr(0.09, 12)
		Out[2]: 0.0938

	-------------------------------------------------------------------------------
	"""
	
	assert numPeriods >= 0, "numPeriods must be >= 0"
	
	if numPeriods > 0:
		return round(((1 + (1.0 * rate/numPeriods))** numPeriods) - 1, 4)
	elif numPeriods == 0:
		return round((math.e ** rate - 1), 4)

def npv(cashFlow, rate):
	"""
	-------------------------------------------------------------------------------
	Usage
		finpy.npv(cashFlowsList, discountRate)

	Notes
		NPV is the sum of present values of all the expected incremental cash flows
		discounted with the discountRate

	Examples
		In [1]: import finpy
		
		In [2]: finpy.npv([-2000, 1000, 800, 600, 200], 0.1)
		Out[2]: 157.64
	
	-------------------------------------------------------------------------------
	"""
	if type(rate) == list or type(rate) == tuple:
		return [npv(cashFlow, _rate) for _rate in rate]

	assert len(cashFlow) > 0, "There must be some cashFlow to compute npv"	
	assert rate > 0, "discountRate must be >0 to compute npv"
	return round(sum([amount/((1+rate) ** index) for index, amount in \
										zip(range(len(cashFlow)), cashFlow)]), 2)

def irr(cashFlow):
	"""
	-------------------------------------------------------------------------------
	Usage
		finpy.irr(cashFlowsList)

	Notes
		IRR is the discount rate that makes NPV = 0

	Examples
		In [1]: import finpy
		
		In [2]: finpy.irr([-2000, 1000, 800, 600, 200])
		Out[2]: 0.1449
	
	-------------------------------------------------------------------------------
	"""

	if sys.version.find('.NET') != -1:
		raise NotImplementedError, "No irr in finpy under IronPython"
		
	import numpy

	assert len(cashFlow) > 0, "There must be some cashFlow to compute irr"
	
	cashFlow.reverse()
	p = numpy.poly1d(cashFlow)
	solution = numpy.roots(p)
	i = 0
	I = numpy.NaN
	for _solution in solution:
		if _solution.imag == 0 and _solution.real > 0 and _solution.real <= 1:
			I = round((1 / _solution.real) - 1, 4)
			break
	return I
